
#ifndef __CANOPEN_MOTOR_H__
#define __CANOPEN_MOTOR_H__

#ifdef __cplusplus
extern "C" {
#endif

#include "main.h"
#include "Servo_OD.h"
#include "motor_def.h"

#define MASTER_NODE_ID          0x10
//伺服状态字指示的状态
#define STATUS_START            0x0000
#define STATUS_NOT_READY                0x50
#define STATUS_NOT_READY_QUICK_STOP     0x70
#define STATUS_READY            0x31
#define STATUS_SWITCHED_ON      0x33
#define STATUS_OPERATION_EN     0x37
#define STATUS_QUICK_STOP       0x17
#define STATUS_FAULT            0x18

//伺服控制字
#define CONTROL_TO_READY        0x0006
#define CONTROL_TO_SWITCHED_ON  0x0007
#define CONTROL_TO_OPERATION_EN 0x000F
#define CONTROL_TO_QUICKSTOP    0x0002

#define TPDO_NUM_CONTROL_WORD   0x00
#define TPDO_NUM_POS_VEL        0x01
#define TPOD_NUM_TORQUE         0x02

//伺服的控制模式   作废，不需要使用
#define NO_MODE                 0x00
#define PP_MODE                 0x01        // Profile position mode
#define VL_MODE                 0x02        // Velocity mode
#define PV_MODE                 0x03        // Profile velocity mode
#define TQ_MODE                 0x04        // Torque profile mode
#define HM_MODE                 0x06        // Homing mode
#define IP_MODE                 0x07        // Interpolated position mode
#define CSP_MODE                0x08        // Cyclic synchronous position mode
#define CSV_MODE                0x09        // Cyclic synchronous velocity mode
#define CST_MODE                0x0A        // Cyclic synchronous torque mode

#define MAX_TPDO_NUM_PER_NODE   0x02
#define MAX_RPDO_NUM_PER_NODE   0x02

typedef struct net_sdo_od
{
    uint16_t index;
    uint8_t subIndex;
    uint8_t dataType;
    uint32_t count;
    uint32_t data;
}net_sdo_od_t;

typedef struct net_sdo_prameter
{
    CO_Data* d;
    uint8_t targetID;
    net_sdo_od_t od;
    void* pdata;
    SDOCallback_t callback;
}net_sdo_prameter_t;


/**
 * @struct local_od_t
 * @brief CANopen对象字典条目的结构体。
 */
typedef struct {
    uint32_t index; /**< 对象字典索引。 */
    uint8_t subIndex; /**< 对象字典子索引。 */
    uint32_t data; /**< 对象字典数值。 */
    uint32_t size; /**< 对象字典数值的大小（字节数）。 */
} local_od_t;

/*
 * 用此结构体将canfestivel生成的字典指向canopen_motor中的变量，
 * 则canfestivel在改写变量以及使用变量的时候可以直接从此处取值。
 */
typedef struct redirect_od_var
{
    uint16_t index;
    uint8_t subIndex;
    void* pnewvar;
}redirect_od_var_t;

typedef union
{
    uint16_t statusWord;
    struct
    {
        uint16_t stdStatus:8;
        uint16_t manufacturerDefine:1;
        uint16_t isRemote:1;
        uint16_t posReach:1;
        uint16_t posOverflow:1;
        uint16_t posCanRcv:1;
        uint16_t poserr:1;
    }statusBit;
}pp_status_t;

typedef struct canopen_motor
{
    uint8_t     nodeId;                         /**< CANopen电机的节点ID。 */

    int8_t      modesOfOperation;               // 6060 模式选择  CANopen电机的操作模式
    int8_t      modesOfCurrent;                 // 6061 当前模式
    uint16_t    controlWord;                    // 6040 控制字
    pp_status_t statusWord;                     // 6041 状态字
    /* 位置模式 */
    int32_t     targetPos;                      // 607A 设置目标位置
    uint32_t    profileVel;                     // 6081 设置位置模式的速度
    int32_t     actualPos;                      // 6064 目标当前实际位置
    /* 速度模式 */
    int32_t     targetVel;                      // 60FF 设置目标速度
    int32_t     actualVel;                      // 606C 目标当前实际速度
    /* 转矩模式 */
    int16_t     targetTorque;                   // 6071 设置目标转矩 1‰
    int16_t     actualTorque;                   // 6077 目标当前实际转矩

    /* 轮廓模式最高速度限制 */
    uint32_t    maxProfileVel;                  // 带轮廓模式的最高速限制

    int32_t     homePul;                        // 在原点处的脉冲位置
    int32_t     curPul;                         // 上传的当前脉冲位置
    motor_home_status_t homeStatus;
    /* SDO回复信号量 */
    rt_sem_t    semSdoReply;


}canopen_motor_t;

typedef enum
{
    NOERR,
    IDERR,      // nodeid 错误
    STATUSERR,  // 电机当前状态不对，具体状态需通过 Motor_Get_MotorStatus 函数查询
    MODEERR,    // 电机当前的模式不对 modesofoperation
}motor_err_t;


canopen_motor_t* Canopen_Motor_Get(uint8_t nodeId);
motor_err_t Canopen_Motor_Set_OperationMode(uint8_t nodeId,uint8_t mode);
void Canopen_Config_TQ_OD(uint8_t nodeId);
motor_err_t Canopen_Motor_Set_TargetTorque(uint8_t nodeId,int16_t torque,uint32_t maxSpeed);
motor_err_t Canopen_Motor_Set_TargetPos(uint8_t nodeId,int32_t pos,uint32_t vel);
int Canopen_Motor_Get_Pos(uint8_t nodeId);
int Canopen_Motor_Get_Angle(uint8_t nodeId);
int Canopen_Motor_Get_Vel(uint8_t nodeId);
void Canopen_Motor_Set_Zero(uint8_t nodeId,uint8_t runMode);
void Canopen_Motor_Set_HomePul(uint8_t nodeId);
void Canopen_Motor_Home_Start(uint8_t nodeId);
void Canopen_Motor_Home_Move(uint8_t nodeId,int32_t plus,uint32_t vel);
motor_home_status_t Canopen_Motor_HomeStatus_Set(uint8_t nodeId,uint8_t status);
motor_home_status_t Canopen_Motor_HomeStatus_Get(uint8_t nodeId);
void Canopen_Motor_Stop_Node(void);

/* 伺服参数设置API */
rt_err_t Canopen_Motor_WriteSdo_16Bit(uint8_t nodeId,uint16_t index,uint8_t subIndex,uint16_t data);
rt_err_t Canopen_Motor_ReadSdo_16Bit(uint8_t nodeId,uint16_t index,uint8_t subIndex,uint16_t* data);




#ifdef __cplusplus
}
#endif

#endif /* __CAN_H__ */

